Repository navigation
fix(responses): enforce required tools in native combo streams - #7831
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Required-tool fulfillment and hosted substitutions src/adapters/base.ts, src/adapters/openai-responses/image-gen.ts, src/adapters/openai-responses/passthrough.ts, src/server/responses/combo-required-tool-fulfillments.ts, src/server/responses-image-gen-repair.ts, structure/data-planes/images.md, tests/server/server-combo-stream-send-contract.test.ts |
Adapter requests record hosted image-tool substitutions. Required-tool fulfillment checks caller intent against the outbound request. Tests cover substitutions in queued and preset requests, including changed provider configuration. |
Required-tool stream guard and delivery src/server/responses/combo-required-tool-stream.ts, src/server/responses/passthrough-delivery.ts, tests/server/server-combo-stream-required-tool.test.ts, tests/server/server-combo-stream-hosted-tool-contract.test.ts, tests/server/server-combo-required-tool-contract.test.ts, tests/helpers/responses-core-source.ts |
The guard inspects normalized output and rewrites qualifying missing-call completions to response.failed. Passthrough delivery uses the guard for eligible combo streams. Server tests cover required-call matching, failover, committed output, hosted calls, and cancellation. |
Bounded preflight and combo integration src/server/responses/combo-stream-preflight.ts, src/server/responses/core-combo.ts, tests/routing/combo-required-tool-stream-preflight.test.ts |
Preflight holds reasoning frames for up to one second, preserves an in-flight read, and handles cancellation. Combo execution supplies required-tool and abort options. Routing tests cover deadlines, commitment, and cancellation. |
Streaming contract and test coverage docs-site/src/content/docs/reference/proxy-formats.md, structure/transports/responses-combo-boundaries.md, structure/transports/responses-failover.md, structure/transports/responses.md, scripts/test-layout/layout.json, scripts/test-layout/layout-combos.json, tests/fixtures/test-layout-expected.json |
Documentation describes the streaming contract and distinguishes it from direct native and translated Chat routes. Test-layout files register the added suites. |
Priority:
Estimated code review effort: 3 (Moderate) | ~30 minutes
Change: Bug fix
Sequence Diagram(s)
sequenceDiagram
participant executeComboResponses
participant preflightComboStreamResponse
participant deliverPassthroughResponse
participant createComboRequiredToolStreamGuard
participant Client
executeComboResponses->>preflightComboStreamResponse: provide child response and required-tool prelude option
preflightComboStreamResponse->>deliverPassthroughResponse: accept response after commitment or deadline
deliverPassthroughResponse->>createComboRequiredToolStreamGuard: inspect and rewrite normalized stream events
createComboRequiredToolStreamGuard->>Client: forward stream or typed failure
Possibly related PRs
- lidge-jun/opencodex#7741: Implements buffered native Responses required-tool validation that this change extends to streaming combo children.
- lidge-jun/opencodex#7711: Adds buffered required-tool validation and typed failures, which this change extends to native SSE combo children.
Merge Risk: 
Minimal · up to 611cb
-
No merge-blocking issue was identified in the reviewed change.
Pre-merge checks: 
4 · 
1
-
Failed checks: 1 warning Passed checks: 4 passedFull details: Docstring Coverage
-
Explanation
Docstring coverage is 34.78% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 23 functions across 15 files.
Resolution
Write docstrings for the functions missing them to satisfy the coverage threshold.
-
Finishing Touches: 💡 1
-
📝 Generate docstrings: 💡
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6b94742e3f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
✅ Deterministic PR hygiene checks passed. |
passthrough-delivery.ts now reaches combo-required-tool-stream.ts and combo-required-tool-fulfillments.ts, so the core module boundary test expects both in RESPONSES_CORE_MODULES, which also puts them under its line cap.
|
Maintainer dev integration decision (per MAINTAINERS.md).
|
Summary
A streaming Responses request with
tool_choice: "required"(or a named function) routed through a combo could end asresponse.completedwith zero calls when the selected native child ignored the tool contract, and the combo treated that as success. The buffered half was fixed in #7741 and translated Chat in #7463; this covers native SSE combo children.For those children only, the required-tool contract is now checked on the stream:
response.failed(required_tool_contract_unsatisfied) instead of a falsecompleted. There is no replay or hop after commitment, and completion callbacks and continuation storage do not fire.mcp.pingandmcp__pingechoes produce one consistent decision.Non-required requests, direct native requests, translated Chat, runTurn and WebSocket paths are unchanged.
Refs #7456 (streaming half).
Verification
tests/server/server-combo-stream-required-tool.test.tsandtests/routing/combo-required-tool-stream-preflight.test.ts(new): required and named choices, held vs committed output, typed failure with one send, hosted-tool effects, call-ID ownership, the 151-tool fallback/call/result cycle, eight eager/tee alias combinations, fake-clock hold expiry (silence, trickle, cancellation, byte/chunk caps). Before the source change: 4 pass / 9 fail; before the round-1 fixes: 42 pass / 8 fail.OCX_TEST_NO_QUEUE=1, Bun 1.4.4), 12 files including the existing combo preflight, zero-output failover, tool-loop continuation, buffered contract, Chat required-tool, layout, file-size ratchet and Lab boundary tests: 250 pass / 0 fail.bun run typecheck,bun run structure:check,bun run privacy:scan,git diff --check: pass.bun run testandtest:changed(shared host under load); left to CI.Checklist
Summary by CodeRabbit
Bug Fixes
Documentation